package api

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"gitee.com/war2001/NiuMaEasyGo/model"
	"gitee.com/war2001/NiuMaEasyGo/nm_core/middleware"
	"gitee.com/war2001/NiuMaEasyGo/nm_core/router"
	"gitee.com/war2001/NiuMaEasyGo/nm_core/storage"
	"github.com/gin-gonic/gin"
)

// FileController 文件控制器
type FileController struct {
	fileService model.FileService
}

// NewFileController 创建文件控制器
func NewFileController(fileService model.FileService) *FileController {
	return &FileController{
		fileService: fileService,
	}
}

// UploadMetadata 上传文件元数据
func (c *FileController) UploadMetadata() router.RouteMetadata {
	return router.RouteMetadata{
		Title:        "上传文件",
		Path:         "",
		Component:    "",
		Icon:         "",
		Permission:   "system:file:upload",
		ParentPath:   "/system/file",
		MenuType:     "button",
		MenuCategory: "common",
		Method:       "POST",
		APIPath:      "/file/upload",
		RequireAuth:  true,
		OrderNum:     1,
	}
}

// DeleteMetadata 删除文件元数据
func (c *FileController) DeleteMetadata() router.RouteMetadata {
	return router.RouteMetadata{
		Title:        "删除文件",
		Path:         "",
		Component:    "",
		Icon:         "",
		Permission:   "system:file:delete",
		ParentPath:   "/system/file",
		MenuType:     "button",
		MenuCategory: "common",
		Method:       "DELETE",
		APIPath:      "/file/:id",
		RequireAuth:  true,
		OrderNum:     2,
	}
}

// ListMetadata 文件列表元数据
func (c *FileController) ListMetadata() router.RouteMetadata {
	return router.RouteMetadata{
		Title:        "文件管理",
		Path:         "/system/file",
		Component:    "/system/file/index",
		Icon:         "file",
		Permission:   "system:file:list",
		ParentPath:   "/system",
		MenuType:     "menu",
		MenuCategory: "system",
		Method:       "GET",
		APIPath:      "/file/list",
		RequireAuth:  true,
		OrderNum:     5,
	}
}

// GetMetadata 获取文件元数据
func (c *FileController) GetMetadata() router.RouteMetadata {
	return router.RouteMetadata{
		Title:        "文件详情",
		Path:         "",
		Component:    "",
		Icon:         "",
		Permission:   "system:file:query",
		ParentPath:   "/system/file",
		MenuType:     "button",
		MenuCategory: "common",
		Method:       "GET",
		APIPath:      "/file/:id",
		RequireAuth:  true,
		OrderNum:     3,
	}
}

// Upload 上传文件
func (c *FileController) Upload(ctx *gin.Context) {
	// 获取当前用户ID
	userID, exists := ctx.Get("user_id")
	if !exists {
		middleware.ResponseError(ctx, 401, "未获取到用户信息")
		return
	}

	// 获取当前租户ID
	tenantID, exists := ctx.Get("tenant_id")
	if !exists {
		middleware.ResponseError(ctx, 401, "未获取到租户信息")
		return
	}

	// 获取文件分类
	category := ctx.DefaultPostForm("category", "default")

	// 获取文件标签
	tags := ctx.DefaultPostForm("tags", "")

	// 获取备注
	remark := ctx.DefaultPostForm("remark", "")

	// 获取是否公开
	isPublicStr := ctx.DefaultPostForm("is_public", "false")
	isPublic := isPublicStr == "true"

	// 获取上传的文件
	file, err := ctx.FormFile("file")
	if err != nil {
		middleware.ResponseError(ctx, 400, "获取上传文件失败: "+err.Error())
		return
	}

	// 获取文件名
	filename := storage.GetSafeFilename(file.Filename)

	// 获取文件大小
	fileSize := file.Size

	// 获取文件内容类型
	contentType := file.Header.Get("Content-Type")
	if contentType == "" {
		// 根据文件扩展名猜测内容类型
		ext := filepath.Ext(filename)
		contentType = getContentTypeByExt(ext)
	}

	// 打开文件
	src, err := file.Open()
	if err != nil {
		middleware.ResponseError(ctx, 500, "打开上传文件失败: "+err.Error())
		return
	}
	defer src.Close()

	// 读取文件内容
	fileData, err := ioutil.ReadAll(src)
	if err != nil {
		middleware.ResponseError(ctx, 500, "读取上传文件失败: "+err.Error())
		return
	}

	// 创建文件记录
	fileModel := &model.File{
		Name:        filename,
		ContentType: contentType,
		Size:        fileSize,
		UploadTime:  time.Now(),
		UserID:      userID.(uint),
		TenantID:    tenantID.(uint),
		IsPublic:    isPublic,
		Category:    category,
		Tags:        tags,
		Remark:      remark,
	}

	// 上传文件
	if err := c.fileService.Upload(fileModel, fileData); err != nil {
		middleware.ResponseError(ctx, 500, "上传文件失败: "+err.Error())
		return
	}

	// 返回文件信息
	middleware.ResponseSuccess(ctx, gin.H{
		"id":           fileModel.ID,
		"name":         fileModel.Name,
		"url":          fileModel.URL,
		"size":         fileModel.Size,
		"content_type": fileModel.ContentType,
		"upload_time":  fileModel.UploadTime,
	})
}

// Download 下载文件
func (c *FileController) Download(ctx *gin.Context) {
	// 获取文件ID
	idStr := ctx.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 32)
	if err != nil {
		middleware.ResponseError(ctx, 400, "无效的文件ID")
		return
	}

	// 获取文件信息
	file, err := c.fileService.GetByID(uint(id))
	if err != nil {
		middleware.ResponseError(ctx, 404, "文件不存在: "+err.Error())
		return
	}

	// 获取文件内容
	data, err := c.fileService.GetContent(uint(id))
	if err != nil {
		middleware.ResponseError(ctx, 500, "获取文件内容失败: "+err.Error())
		return
	}

	// 设置响应头
	ctx.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", file.Name))
	ctx.Header("Content-Type", file.ContentType)
	ctx.Header("Content-Length", strconv.FormatInt(file.Size, 10))

	// 发送文件内容
	ctx.Data(http.StatusOK, file.ContentType, data)
}

// GetURL 获取文件访问URL
func (c *FileController) GetURL(ctx *gin.Context) {
	// 获取文件ID
	idStr := ctx.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 32)
	if err != nil {
		middleware.ResponseError(ctx, 400, "无效的文件ID")
		return
	}

	// 获取过期时间
	expirationStr := ctx.DefaultQuery("expiration", "3600")
	expiration, err := strconv.ParseInt(expirationStr, 10, 64)
	if err != nil {
		expiration = 3600 // 默认1小时
	}

	// 获取文件访问URL
	url, err := c.fileService.GetURL(uint(id), time.Duration(expiration)*time.Second)
	if err != nil {
		middleware.ResponseError(ctx, 500, "获取文件访问URL失败: "+err.Error())
		return
	}

	// 返回URL
	middleware.ResponseSuccess(ctx, gin.H{
		"url":        url,
		"expiration": expiration,
	})
}

// List 获取文件列表
func (c *FileController) List(ctx *gin.Context) {
	// 获取分页参数
	page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(ctx.DefaultQuery("page_size", "10"))

	// 构建查询条件
	query := make(map[string]interface{})

	// 获取查询参数
	if name := ctx.Query("name"); name != "" {
		query["name"] = name
	}
	if category := ctx.Query("category"); category != "" {
		query["category"] = category
	}
	if tags := ctx.Query("tags"); tags != "" {
		query["tags"] = tags
	}
	if userIDStr := ctx.Query("user_id"); userIDStr != "" {
		userID, _ := strconv.ParseUint(userIDStr, 10, 32)
		query["user_id"] = uint(userID)
	}
	if tenantIDStr := ctx.Query("tenant_id"); tenantIDStr != "" {
		tenantID, _ := strconv.ParseUint(tenantIDStr, 10, 32)
		query["tenant_id"] = uint(tenantID)
	}
	if storage := ctx.Query("storage"); storage != "" {
		query["storage"] = storage
	}
	if isPublicStr := ctx.Query("is_public"); isPublicStr != "" {
		isPublic := isPublicStr == "true"
		query["is_public"] = isPublic
	}
	if startTimeStr := ctx.Query("start_time"); startTimeStr != "" {
		startTime, err := time.Parse("2006-01-02 15:04:05", startTimeStr)
		if err == nil {
			query["start_time"] = startTime
		}
	}
	if endTimeStr := ctx.Query("end_time"); endTimeStr != "" {
		endTime, err := time.Parse("2006-01-02 15:04:05", endTimeStr)
		if err == nil {
			query["end_time"] = endTime
		}
	}

	// 获取文件列表
	files, total, err := c.fileService.List(page, pageSize, query)
	if err != nil {
		middleware.ResponseError(ctx, 500, "获取文件列表失败: "+err.Error())
		return
	}

	// 返回文件列表
	middleware.ResponseSuccess(ctx, gin.H{
		"list":  files,
		"total": total,
		"page":  page,
		"size":  pageSize,
	})
}

// Delete 删除文件
func (c *FileController) Delete(ctx *gin.Context) {
	// 获取文件ID
	idStr := ctx.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 32)
	if err != nil {
		middleware.ResponseError(ctx, 400, "无效的文件ID")
		return
	}

	// 删除文件
	if err := c.fileService.Delete(uint(id)); err != nil {
		middleware.ResponseError(ctx, 500, "删除文件失败: "+err.Error())
		return
	}

	// 返回成功
	middleware.ResponseSuccess(ctx, gin.H{
		"message": "删除文件成功",
	})
}

// BatchDelete 批量删除文件
func (c *FileController) BatchDelete(ctx *gin.Context) {
	// 获取文件ID列表
	var req struct {
		IDs []uint `json:"ids"`
	}
	if err := ctx.ShouldBindJSON(&req); err != nil {
		middleware.ResponseError(ctx, 400, "无效的请求参数: "+err.Error())
		return
	}

	// 批量删除文件
	if err := c.fileService.BatchDelete(req.IDs); err != nil {
		middleware.ResponseError(ctx, 500, "批量删除文件失败: "+err.Error())
		return
	}

	// 返回成功
	middleware.ResponseSuccess(ctx, gin.H{
		"message": "批量删除文件成功",
	})
}

// RegisterRoutes 注册路由
func (c *FileController) RegisterRoutes(r *gin.RouterGroup) {
	file := r.Group("/file")
	{
		// 需要认证的接口
		authFile := file.Group("")
		authFile.Use(middleware.JWTAuth())
		{
			authFile.POST("/upload", c.Upload)
			authFile.GET("/download/:id", c.Download)
			authFile.GET("/list", c.List)
			authFile.GET("/info/:id", c.GetInfo)
			authFile.DELETE("/:id", c.Delete)
			authFile.POST("/batch-delete", c.BatchDelete)
			authFile.GET("/url/:id", c.GetURL)
		}
	}
}

// getContentTypeByExt 根据文件扩展名获取内容类型
func getContentTypeByExt(ext string) string {
	ext = strings.ToLower(ext)
	switch ext {
	case ".jpg", ".jpeg":
		return "image/jpeg"
	case ".png":
		return "image/png"
	case ".gif":
		return "image/gif"
	case ".webp":
		return "image/webp"
	case ".svg":
		return "image/svg+xml"
	case ".pdf":
		return "application/pdf"
	case ".doc":
		return "application/msword"
	case ".docx":
		return "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
	case ".xls":
		return "application/vnd.ms-excel"
	case ".xlsx":
		return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
	case ".ppt":
		return "application/vnd.ms-powerpoint"
	case ".pptx":
		return "application/vnd.openxmlformats-officedocument.presentationml.presentation"
	case ".txt":
		return "text/plain"
	case ".html", ".htm":
		return "text/html"
	case ".css":
		return "text/css"
	case ".js":
		return "application/javascript"
	case ".json":
		return "application/json"
	case ".xml":
		return "application/xml"
	case ".zip":
		return "application/zip"
	case ".rar":
		return "application/x-rar-compressed"
	case ".7z":
		return "application/x-7z-compressed"
	case ".mp3":
		return "audio/mpeg"
	case ".mp4":
		return "video/mp4"
	case ".avi":
		return "video/x-msvideo"
	case ".mov":
		return "video/quicktime"
	default:
		return "application/octet-stream"
	}
}

// GetInfo 获取文件信息
func (c *FileController) GetInfo(ctx *gin.Context) {
	// 获取文件ID
	idStr := ctx.Param("id")
	id, err := strconv.ParseUint(idStr, 10, 32)
	if err != nil {
		middleware.ResponseError(ctx, 400, "无效的文件ID")
		return
	}

	// 获取文件信息
	file, err := c.fileService.GetByID(uint(id))
	if err != nil {
		middleware.ResponseError(ctx, 404, "文件不存在: "+err.Error())
		return
	}

	// 返回文件信息
	middleware.ResponseSuccess(ctx, gin.H{
		"id":           file.ID,
		"name":         file.Name,
		"path":         file.Path,
		"url":          file.URL,
		"size":         file.Size,
		"content_type": file.ContentType,
		"upload_time":  file.UploadTime,
		"user_id":      file.UserID,
		"tenant_id":    file.TenantID,
		"storage":      file.Storage,
		"is_public":    file.IsPublic,
		"category":     file.Category,
		"tags":         file.Tags,
		"remark":       file.Remark,
	})
}
